import { useEffect, useMemo, useState } from 'react';
import {
  Image,
  KeyboardAvoidingView,
  Platform,
  Pressable,
  ScrollView,
  StyleSheet,
  Switch,
  TextInput,
  View,
} from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { ResizeMode, Video } from 'expo-av';
import { useLocalSearchParams } from 'expo-router';

import { ThemedButton } from '@/components/themed-button';
import { ThemedText } from '@/components/themed-text';
import { ThemedView } from '@/components/themed-view';
import { ZoomImageModal } from '@/components/zoom-image-modal';
import { Colors } from '@/constants/theme';
import { useColorScheme } from '@/hooks/use-color-scheme';
import { useTranslation } from '@/localization/i18n';
import { dbPromise, initCoreTables } from '@/services/db';

type TaskRow = {
  id: number;
  name: string;
  description: string | null;
};

type EntryRow = {
  id: number;
  status: string | null;
  notes: string | null;
  meta_json: string | null;
  completed_at: string | null;
};

type MediaRow = {
  uri: string | null;
};

export default function TaskDetailScreen() {
  const { t } = useTranslation();
  const { id } = useLocalSearchParams<{ id?: string | string[] }>();
  const taskId = Number(Array.isArray(id) ? id[0] : id);
  const theme = useColorScheme() ?? 'light';
  const palette = Colors[theme];
  const todayKey = useMemo(() => new Date().toISOString().slice(0, 10), []);

  const [task, setTask] = useState<TaskRow | null>(null);
  const [entryId, setEntryId] = useState<number | null>(null);
  const [status, setStatus] = useState('');
  const [isDone, setIsDone] = useState(false);
  const [notes, setNotes] = useState('');
  const [mediaUris, setMediaUris] = useState<string[]>([]);
  const [activeUri, setActiveUri] = useState<string | null>(null);
  const [zoomUri, setZoomUri] = useState<string | null>(null);
  const [saving, setSaving] = useState(false);
  const [showSaved, setShowSaved] = useState(false);

  useEffect(() => {
    let isActive = true;

    async function loadTask() {
      try {
        await initCoreTables();
        const db = await dbPromise;
        const taskRows = await db.getAllAsync<TaskRow>(
          'SELECT id, name, description FROM daily_tasks WHERE id = ? LIMIT 1;',
          taskId
        );
        const entryRows = await db.getAllAsync<EntryRow>(
          `SELECT id, status, notes, meta_json, completed_at
           FROM daily_task_entries
           WHERE task_id = ? AND substr(completed_at, 1, 10) = ?
           LIMIT 1;`,
          taskId,
          todayKey
        );
        if (!isActive) return;
        setTask(taskRows[0] ?? null);
        const entry = entryRows[0];
        if (entry) {
          setEntryId(entry.id);
          setNotes(entry.notes ?? '');
        const entryStatus = entry.status ?? '';
        setStatus(entryStatus);
        setIsDone(entryStatus === 'done');
          const mediaRows = await db.getAllAsync<MediaRow>(
            'SELECT uri FROM task_entry_media WHERE entry_id = ? ORDER BY created_at ASC;',
            entry.id
          );
          const media = uniqueMediaUris(mediaRows.map((row) => row.uri).filter(Boolean) as string[]);
          const fallback = parseTaskMeta(entry.meta_json)?.photoUri;
          const merged = uniqueMediaUris([
            ...media,
            ...(normalizeMediaUri(fallback) ? [normalizeMediaUri(fallback) as string] : []),
          ]);
          setMediaUris(merged);
          setActiveUri(merged[0] ?? null);
        }
      } catch (error) {
        if (isActive) setStatus(`Error: ${String(error)}`);
      }
    }

    loadTask();
    return () => {
      isActive = false;
    };
  }, [taskId, todayKey]);

  const inputStyle = [
    styles.input,
    {
      borderColor: palette.border,
      backgroundColor: palette.input,
      color: palette.text,
    },
  ];

  async function handleSave(nextStatus?: string) {
    if (!task) return;
    try {
      setSaving(true);
      const db = await dbPromise;
      const now = new Date().toISOString();
      const statusValue = nextStatus ?? (isDone ? 'done' : 'open');
      let currentEntryId = entryId;
      if (!currentEntryId) {
        const result = await db.runAsync(
          'INSERT INTO daily_task_entries (task_id, field_id, notes, status, completed_at, created_at, meta_json) VALUES (?, NULL, ?, ?, ?, ?, ?);',
          task.id,
          notes.trim() || null,
          statusValue,
          now,
          now,
          serializeTaskMeta({ photoUri: mediaUris[0] })
        );
        currentEntryId = Number(result.lastInsertRowId);
        setEntryId(currentEntryId);
      } else {
        await db.runAsync(
          'UPDATE daily_task_entries SET notes = ?, status = ?, completed_at = ?, meta_json = ? WHERE id = ?;',
          notes.trim() || null,
          statusValue,
          now,
          serializeTaskMeta({ photoUri: mediaUris[0] }),
          currentEntryId
        );
      }
      if (currentEntryId) {
        await db.runAsync('DELETE FROM task_entry_media WHERE entry_id = ?;', currentEntryId);
        for (const uri of uniqueMediaUris(mediaUris)) {
          await db.runAsync(
            'INSERT INTO task_entry_media (entry_id, uri, media_type, created_at) VALUES (?, ?, ?, ?);',
            currentEntryId,
            uri,
            isVideoUri(uri) ? 'video' : 'image',
            now
          );
        }
      }
      setStatus(statusValue === 'done' ? t('tasks.done') : t('tasks.open'));
      setShowSaved(true);
      setTimeout(() => {
        setShowSaved(false);
        setStatus('');
      }, 1800);
    } catch (error) {
      setStatus(`Error: ${String(error)}`);
    } finally {
      setSaving(false);
    }
  }

  return (
    <ThemedView style={[styles.container, { backgroundColor: palette.background }]}>
      <KeyboardAvoidingView
        behavior={Platform.OS === 'ios' ? 'padding' : undefined}
        style={styles.keyboardAvoid}>
        <ScrollView contentContainerStyle={styles.content} keyboardShouldPersistTaps="handled">
          <ThemedText type="title">{task?.name ?? t('tasks.title')}</ThemedText>
          {task?.description ? <ThemedText>{task.description}</ThemedText> : null}

          <View style={styles.statusRow}>
            <ThemedText>{t('tasks.done')}</ThemedText>
            <Switch
              value={isDone}
              onValueChange={(value) => setIsDone(value)}
              trackColor={{ false: palette.border, true: palette.tint }}
              thumbColor={palette.card}
            />
          </View>

          <ThemedText>{t('tasks.notePlaceholder')}</ThemedText>
          <TextInput
            value={notes}
            onChangeText={setNotes}
            placeholder={t('tasks.notePlaceholder')}
            placeholderTextColor={palette.placeholder}
            style={inputStyle}
            multiline
          />

          <ThemedText>{t('tasks.addMedia')}</ThemedText>
          {normalizeMediaUri(activeUri) ? (
            isVideoUri(normalizeMediaUri(activeUri) as string) ? (
              <Video
                source={{ uri: normalizeMediaUri(activeUri) as string }}
                style={styles.mediaPreview}
                useNativeControls
                resizeMode={ResizeMode.CONTAIN}
              />
            ) : (
              <Pressable onPress={() => setZoomUri(normalizeMediaUri(activeUri) as string)}>
                <Image source={{ uri: normalizeMediaUri(activeUri) as string }} style={styles.mediaPreview} resizeMode="contain" />
              </Pressable>
            )
          ) : (
            <ThemedText style={styles.photoPlaceholder}>{t('tasks.photo')}</ThemedText>
          )}

          {mediaUris.length > 0 ? (
            <ScrollView horizontal showsHorizontalScrollIndicator={false} style={styles.mediaStrip}>
              {mediaUris.map((uri) => (
                <Pressable key={uri} style={styles.mediaChip} onPress={() => setActiveUri(uri)}>
                  {isVideoUri(uri) ? (
                    <View style={styles.videoThumb}>
                      <ThemedText style={styles.videoThumbText}>▶</ThemedText>
                    </View>
                  ) : (
                    <Image source={{ uri }} style={styles.mediaThumb} resizeMode="cover" />
                  )}
                  <Pressable
                    style={styles.mediaRemove}
                    onPress={(event) => {
                      event.stopPropagation();
                      setMediaUris((prev) => {
                        const next = prev.filter((item) => item !== uri);
                        setActiveUri((current) => (current === uri ? next[0] ?? null : current));
                        return next;
                      });
                    }}>
                    <ThemedText style={styles.mediaRemoveText}>×</ThemedText>
                  </Pressable>
                </Pressable>
              ))}
            </ScrollView>
          ) : null}

          <View style={styles.photoRow}>
            <ThemedButton
              title={t('tasks.pickFromGallery')}
              onPress={() =>
                handlePickMedia((uris) => {
                  if (uris.length === 0) return;
                  setMediaUris((prev) => uniqueMediaUris([...prev, ...uris]));
                  setActiveUri((prev) => prev ?? uris[0]);
                })
              }
              variant="secondary"
            />
            <ThemedButton
              title={t('tasks.takeMedia')}
              onPress={() =>
                handleTakeMedia((uri) => {
                  if (!uri) return;
                  setMediaUris((prev) => uniqueMediaUris([...prev, uri]));
                  setActiveUri((prev) => prev ?? uri);
                })
              }
              variant="secondary"
            />
          </View>

          <View style={styles.actions}>
            <View style={styles.updateGroup}>
              {showSaved ? <ThemedText style={[styles.inlineToastText, { color: palette.success }]}>{t('tasks.saved')}</ThemedText> : null}
              <ThemedButton
                title={saving ? t('tasks.saving') : t('tasks.save')}
                onPress={() => handleSave()}
                disabled={saving}
              />
            </View>
          </View>
        </ScrollView>
      </KeyboardAvoidingView>

      <ZoomImageModal uri={zoomUri} visible={Boolean(zoomUri)} onClose={() => setZoomUri(null)} />
    </ThemedView>
  );
}

async function handlePickMedia(onAdd: (uris: string[]) => void) {
  const result = await ImagePicker.launchImageLibraryAsync({
    mediaTypes: getMediaTypes(),
    quality: 1,
    allowsMultipleSelection: true,
    selectionLimit: 0,
  });
  if (result.canceled) return;
  const uris = (result.assets ?? []).map((asset) => asset.uri).filter(Boolean) as string[];
  if (uris.length === 0) return;
  onAdd(uris);
}

async function handleTakeMedia(onAdd: (uri: string | null) => void) {
  const permission = await ImagePicker.requestCameraPermissionsAsync();
  if (!permission.granted) return;
  const result = await ImagePicker.launchCameraAsync({
    mediaTypes: getMediaTypes(),
    quality: 1,
  });
  if (result.canceled) return;
  const asset = result.assets[0];
  onAdd(asset.uri);
}

function getMediaTypes() {
  const mediaType = (ImagePicker as {
    MediaType?: { Image?: unknown; Images?: unknown; Video?: unknown; Videos?: unknown };
  }).MediaType;
  const imageType = mediaType?.Image ?? mediaType?.Images;
  const videoType = mediaType?.Video ?? mediaType?.Videos;
  if (imageType && videoType) {
    return [imageType, videoType];
  }
  return imageType ?? videoType ?? ['images', 'videos'];
}

function isVideoUri(uri: string) {
  return /\.(mp4|mov|m4v|webm|avi|mkv)(\?.*)?$/i.test(uri);
}

function normalizeMediaUri(uri?: string | null) {
  if (typeof uri !== 'string') return null;
  const trimmed = uri.trim();
  return trimmed ? trimmed : null;
}

function uniqueMediaUris(uris: string[]) {
  const seen = new Set<string>();
  const result: string[] = [];
  for (const uri of uris) {
    if (!uri || seen.has(uri)) continue;
    seen.add(uri);
    result.push(uri);
  }
  return result;
}

function parseTaskMeta(raw: string | null) {
  if (!raw) return {} as { photoUri?: string };
  try {
    return JSON.parse(raw) as { photoUri?: string };
  } catch {
    return {} as { photoUri?: string };
  }
}

function serializeTaskMeta(meta: { photoUri?: string }) {
  if (!meta.photoUri) return null;
  return JSON.stringify(meta);
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  keyboardAvoid: {
    flex: 1,
  },
  content: {
    padding: 16,
    gap: 10,
    paddingBottom: 40,
  },
  input: {
    borderRadius: 10,
    borderWidth: 1,
    paddingHorizontal: 12,
    paddingVertical: 10,
    fontSize: 15,
  },
  mediaPreview: {
    width: '100%',
    height: 220,
    borderRadius: 12,
    backgroundColor: '#1C1C1C',
  },
  photoRow: {
    flexDirection: 'row',
    gap: 8,
  },
  actions: {
    marginTop: 12,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
    gap: 10,
  },
  photoPlaceholder: {
    opacity: 0.6,
  },
  mediaStrip: {
    marginTop: 6,
  },
  mediaChip: {
    width: 72,
    height: 72,
    borderRadius: 10,
    marginRight: 8,
    overflow: 'hidden',
    backgroundColor: '#E6E1D4',
    alignItems: 'center',
    justifyContent: 'center',
  },
  mediaThumb: {
    width: '100%',
    height: '100%',
  },
  videoThumb: {
    width: '100%',
    height: '100%',
    backgroundColor: '#1C1C1C',
    alignItems: 'center',
    justifyContent: 'center',
  },
  videoThumbText: {
    color: '#FFFFFF',
    fontSize: 18,
    fontWeight: '700',
  },
  mediaRemove: {
    position: 'absolute',
    top: 4,
    right: 4,
    width: 18,
    height: 18,
    borderRadius: 9,
    backgroundColor: 'rgba(0,0,0,0.6)',
    alignItems: 'center',
    justifyContent: 'center',
  },
  mediaRemoveText: {
    color: '#FFFFFF',
    fontSize: 12,
    lineHeight: 14,
    fontWeight: '700',
  },
  updateGroup: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  inlineToastText: {
    fontWeight: '700',
    fontSize: 12,
  },
  statusRow: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    marginBottom: 12,
  },
});
